package org.wx.herostory.services.decoder;

import com.google.protobuf.GeneratedMessageV3;
import com.google.protobuf.Message;
import lombok.extern.slf4j.Slf4j;
import org.wx.herostory.msg.GameMsgProtocol;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

/**
 * @description: 解码器
 * @author: wangxun
 * @createDate: 2021/3/1
 * @version: 1.0
 */
@Slf4j
public class GameMsgRecognizer {
    /**
     * 命令和操作对应的字典
     */
    static  private  final Map<Integer, GeneratedMessageV3> _msgCodeAndMsgObjMap = new HashMap<>();

    /**
     * 操作类地址和命令对应的字典
     */
    static  private  final Map<Class<?> , Integer> _msgClazzAndMsgCodeMap = new HashMap<>();

    private GameMsgRecognizer(){}

    static public void init(){
        log.info("===============开始消息ID与消息实体的映射================");

        // 得到protoBuf中的内部类集合
        Class<?>[] innerClasses = GameMsgProtocol.class.getDeclaredClasses();
        for (Class<?> innerClass : innerClasses) {
            // 判断是不是ProtocBuf中可分配的
            if(null == innerClass || !GeneratedMessageV3.class.isAssignableFrom(innerClass)){
                continue;
            }
            // 简单类名
            String clazzName = innerClass.getSimpleName();
            clazzName = clazzName.toLowerCase();

            for (GameMsgProtocol.MsgCode msgCode : GameMsgProtocol.MsgCode.values()) {
                if(null == msgCode){
                    continue;
                }
                String strMsgCode = msgCode.name().replace("_", "").toLowerCase();

                try {
                    if(!strMsgCode.startsWith(clazzName)){
                        continue;
                    }

                    // 构建实体
                    Object newInstance = innerClass.getDeclaredMethod("getDefaultInstance").invoke(innerClass);

                    log.info("{} <===> {}",innerClass.getName(),msgCode.getNumber());

                    _msgCodeAndMsgObjMap.put(msgCode.getNumber(), (GeneratedMessageV3) newInstance);

                    _msgClazzAndMsgCodeMap.put(innerClass,msgCode.getNumber());
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                }

            }

        }

    }

    /**
     * 根据命令获取动作指令的建造器
     * @param msgCode
     * @return
     */
    static public Message.Builder getBuilderByMsgCode(int msgCode){
        if(msgCode>=0){
            return _msgCodeAndMsgObjMap.get(msgCode).newBuilderForType();
        }
        return null;
    }

    /**
     * 根据动作指令的类模型，返回命令
     * @param msgClazz
     * @return
     */
    static public int getMsgCodeByClazz(Class<?> msgClazz){
        if(null == msgClazz){
            return -1;
        }
        Integer msgCode = _msgClazzAndMsgCodeMap.get(msgClazz);
        if(null == msgCode){
            return -1;
        }
        return msgCode.intValue();

    }
}
